import { defineNuxtPlugin } from '#app'
import Modal from '~/components/ui/AdminModal.vue'
import { createApp, h, ref } from 'vue'

type ModalOptions = {
  title?: string
  showHeader?: boolean
  showFooter?: boolean
  showCloseButton?: boolean
  showCancelButton?: boolean
  showConfirmButton?: boolean
  cancelText?: string
  confirmText?: string
  closeOnClickOutside?: boolean
  closeOnEsc?: boolean
  maxWidth?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'
  overlayClass?: string
  containerClass?: string
  modalClass?: string
  headerClass?: string
  titleClass?: string
  contentClass?: string
  footerClass?: string
  closeButtonClass?: string
  cancelButtonClass?: string
  confirmButtonClass?: string
}

export default defineNuxtPlugin((nuxtApp) => {
  const showModal = (options: ModalOptions & { content?: string }, slots?: { default?: () => any; footer?: () => any }) => {
    const mountNode = document.createElement('div')
    document.body.appendChild(mountNode)

    const isOpen = ref(true)

    const app = createApp({
      setup() {
        const handleClose = () => {
          isOpen.value = false
          setTimeout(() => {
            app.unmount()
            document.body.removeChild(mountNode)
          }, 300)
        }

        return () => h(Modal, {
          isOpen: isOpen.value,
          title: options.title,
          showHeader: options.showHeader,
          showFooter: options.showFooter,
          showCloseButton: options.showCloseButton,
          showCancelButton: options.showCancelButton,
          showConfirmButton: options.showConfirmButton,
          cancelText: options.cancelText,
          confirmText: options.confirmText,
          closeOnClickOutside: options.closeOnClickOutside,
          closeOnEsc: options.closeOnEsc,
          maxWidth: options.maxWidth,
          overlayClass: options.overlayClass,
          containerClass: options.containerClass,
          modalClass: options.modalClass,
          headerClass: options.headerClass,
          titleClass: options.titleClass,
          contentClass: options.contentClass,
          footerClass: options.footerClass,
          closeButtonClass: options.closeButtonClass,
          cancelButtonClass: options.cancelButtonClass,
          confirmButtonClass: options.confirmButtonClass,
          'onUpdate:isOpen': (val: boolean) => {
            isOpen.value = val
            if (!val) handleClose()
          },
          onClose: handleClose,
        }, {
          default: slots?.default || (() => options.content),
          footer: slots?.footer
        })
      }
    })

    app.mount(mountNode)

    return {
      close: () => {
        isOpen.value = false
        setTimeout(() => {
          app.unmount()
          document.body.removeChild(mountNode)
        }, 300)
      }
    }
  }

  const confirm = (options: ModalOptions & { content?: string }) => {
    return new Promise((resolve) => {
      const mountNode = document.createElement('div')
      document.body.appendChild(mountNode)

      const isOpen = ref(true)

      const app = createApp({
        setup() {
          const handleConfirm = () => {
            resolve(true)
            isOpen.value = false
            setTimeout(() => {
              app.unmount()
              document.body.removeChild(mountNode)
            }, 300)
          }

          const handleCancel = () => {
            resolve(false)
            isOpen.value = false
            setTimeout(() => {
              app.unmount()
              document.body.removeChild(mountNode)
            }, 300)
          }

          return () => h(Modal, {
            isOpen: isOpen.value,
            title: options.title,
            showHeader: options.showHeader,
            showFooter: options.showFooter,
            showCloseButton: options.showCloseButton,
            showCancelButton: options.showCancelButton,
            showConfirmButton: options.showConfirmButton,
            cancelText: options.cancelText,
            confirmText: options.confirmText,
            closeOnClickOutside: options.closeOnClickOutside,
            closeOnEsc: options.closeOnEsc,
            maxWidth: options.maxWidth,
            overlayClass: options.overlayClass,
            containerClass: options.containerClass,
            modalClass: options.modalClass,
            headerClass: options.headerClass,
            titleClass: options.titleClass,
            contentClass: options.contentClass,
            footerClass: options.footerClass,
            closeButtonClass: options.closeButtonClass,
            cancelButtonClass: options.cancelButtonClass,
            confirmButtonClass: options.confirmButtonClass,
            'onUpdate:isOpen': (val: boolean) => {
              isOpen.value = val
              if (!val) {
                resolve(false)
                setTimeout(() => {
                  app.unmount()
                  document.body.removeChild(mountNode)
                }, 300)
              }
            },
            onClose: () => {
              resolve(false)
              isOpen.value = false
              setTimeout(() => {
                app.unmount()
                document.body.removeChild(mountNode)
              }, 300)
            },
            onCancel: handleCancel,
            onConfirm: handleConfirm,
          }, {
            default: () => options.content
          })
        }
      })

      app.mount(mountNode)
    })
  }

  return {
    provide: {
      modal: {
        show: showModal,
        confirm
      }
    }
  }
})